// Net.h

#pragma once
#ifndef NET_H_INCLUDED
#define NET_H_INCLUDED

#include "World.h"

class Net
{
public:
	enum {
		GamePort=1236,
		MsgTextMaxLen=64,
		BufferSize=2048,
		MaxPacketSize=1000
	};

	UdpSocket m_xSock;
	IPAddr m_xLocalAddress;
	int m_iScanCounter;	// -1:inactive 0-n:scanning -2:done
	byte* m_aiBuffer;
	DArray<IPAddr> m_axKnownHosts;

	bool m_hasInit;
	bool m_bInGame;
	//bool m_bHostAuthorativeUpdate;


	Net();
	~Net();

	dword Init();
	void Shut();

	bool IsRunning() const;

	int ScanNetwork();
	void Think();

	void DumpPeers();
	void SortPeers();

	void BroadcastLocalState();
	

#pragma pack(push,1)

	enum MsgType
	{
		MT_Ping=0x80,
		MT_Pong=0x81,
		MT_Quit=3,
		MT_WorldState=4
		
	};

	struct Msg
	{
		byte m_iType;
	};

	struct MsgWorldState : public Msg
	{
		dword m_yPacketID;		//type, set to 4 dword 		//packetID, should be unique, get current tick value is a recommendation 
		dword m_dwSenderIP;		//senderID, the ip of the sender [is this necessary?] 
		byte m_yNumPlayers;		//number of players in game, max 16  

		PlayerState m_axPlayerStates[WorldState::MaxPlayers];
	};

	static int SizeOfMsg(byte p_yType);
	Msg* AllocMsg(byte p_yType);
	void FreeMsg(Msg* p_pxMsg);

#pragma pack(pop)

	struct Peer
	{
		IPAddr m_xAddr;
		DArray<Msg*> m_apxQueueIn;
		DArray<Msg*> m_apxQueueOut;
		WorldState m_xState;
		bool m_bStateUpdated;

		unsigned int m_iLastMessageTime;

		Peer();
		~Peer();
		void Swap(Peer& p_xP);
	};

	DArray<Peer> m_axPeers;

	int FindPeer(dword p_dwID);
	int GetMajorityScore(int p_iPeerIdx);

	void HandleMsg(const IPAddr& p_xAddr,Msg* p_pxMsg);
	void FillWorldStateMsg(const WorldState& p_xW, MsgWorldState* p_msg);

	int ImportRemotes(Peer* p_remotes);
};

#endif NET_H_INCLUDED
